package com.hyh.admin.recommend;

import org.springframework.stereotype.Service;
import java.util.*;

@Service
public class ItemBasedCFRecommendationService {

    /**
     * 计算课程相似度矩阵（余弦相似度）
     */
    public Map<String, Map<String, Double>> computeCourseSimilarity(Map<String, Map<String, Double>> userRatings) {
        // 课程评分矩阵
        Map<String, Map<String, Double>> courseRatings = new HashMap<>();

        // 转换用户-课程评分矩阵为课程-用户评分矩阵
        for (Map.Entry<String, Map<String, Double>> userEntry : userRatings.entrySet()) {
            String user = userEntry.getKey();
            for (Map.Entry<String, Double> courseEntry : userEntry.getValue().entrySet()) {
                courseRatings.computeIfAbsent(courseEntry.getKey(), k -> new HashMap<>()).put(user, courseEntry.getValue());
            }
        }

        // 计算课程相似度
        Map<String, Map<String, Double>> courseSimilarity = new HashMap<>();
        List<String> courses = new ArrayList<>(courseRatings.keySet());

        for (int i = 0; i < courses.size(); i++) {
            for (int j = i + 1; j < courses.size(); j++) {
                String course1 = courses.get(i);
                String course2 = courses.get(j);

                // 获取共同用户
                Set<String> commonUsers = new HashSet<>(courseRatings.get(course1).keySet());
                commonUsers.retainAll(courseRatings.get(course2).keySet());

                if (commonUsers.isEmpty()) continue;

                // 计算余弦相似度
                double dotProduct = 0, normA = 0, normB = 0;
                for (String user : commonUsers) {
                    double rating1 = courseRatings.get(course1).get(user);
                    double rating2 = courseRatings.get(course2).get(user);
                    dotProduct += rating1 * rating2;
                    normA += Math.pow(rating1, 2);
                    normB += Math.pow(rating2, 2);
                }

                double similarity = dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));

                courseSimilarity.computeIfAbsent(course1, k -> new HashMap<>()).put(course2, similarity);
                courseSimilarity.computeIfAbsent(course2, k -> new HashMap<>()).put(course1, similarity);
            }
        }
        return courseSimilarity;
    }

    /**
     * 预测用户对未评分课程的评分
     */
    public Map<String, Double> predictUserRatings(String user, Map<String, Map<String, Double>> userRatings, Map<String, Map<String, Double>> courseSimilarity) {
        Map<String, Double> userRatedCourses = userRatings.getOrDefault(user, new HashMap<>());
        Map<String, Double> predictedRatings = new HashMap<>();

        for (String targetCourse : courseSimilarity.keySet()) {
            if (userRatedCourses.containsKey(targetCourse)) continue; // 已评分课程跳过

            double numerator = 0, denominator = 0;
            for (Map.Entry<String, Double> ratedCourseEntry : userRatedCourses.entrySet()) {
                String ratedCourse = ratedCourseEntry.getKey();
                double rating = ratedCourseEntry.getValue();

                double similarity = courseSimilarity.getOrDefault(targetCourse, new HashMap<>()).getOrDefault(ratedCourse, 0.0);
                numerator += similarity * rating;
                denominator += Math.abs(similarity);
            }

            if (denominator != 0) {
                predictedRatings.put(targetCourse, numerator / denominator);
            }
        }

        // 按预测评分降序排列
        return sortByValue(predictedRatings);
    }

    /**
     * 按评分降序排序
     */
    private Map<String, Double> sortByValue(Map<String, Double> map) {
        List<Map.Entry<String, Double>> list = new ArrayList<>(map.entrySet());
        list.sort((a, b) -> Double.compare(b.getValue(), a.getValue()));

        Map<String, Double> sortedMap = new LinkedHashMap<>();
        for (Map.Entry<String, Double> entry : list) {
            sortedMap.put(entry.getKey(), entry.getValue());
        }
        return sortedMap;
    }
}
